/**
 * @file test_rect_buffer.cpp
 * @author 逆流 (1171267147@qq.com)
 * @brief 测试OpenCL readbufferrect/writebufferrect接口的单元测试
 * @version 0.1
 * @date 2025-11-25
 *
 * @copyright Copyright (c) 2025
 * @note 此文件由 iFlow CLI 生成和维护
 *
 */
#define BOOST_TEST_MODULE TestRectBuffer
#include <CL/cl.h>

#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <boost/format/format_fwd.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/test/tools/old/interface.hpp>
#include <boost/test/unit_test_log.hpp>
#include <boost/timer/timer.hpp>
#include <cstddef>
#include <cstring>
#include <fstream>
#include <iostream>
#include <vector>

#include "utility.hpp"
#include "wrapper.hpp"

using boost::format;

class RectBufferTestFixture {
protected:
    RectBufferTestFixture()
    {
        cl_.Init();

        context_ = cl_.GetContext();
        BOOST_TEST_REQUIRE(context_);

        queue_ = cl_.GetQueue();
        BOOST_TEST_REQUIRE(queue_);
    }

    ~RectBufferTestFixture() { cl_.DeInit(); }

    CLWrapper        cl_;
    cl_context       context_;
    cl_command_queue queue_;
};

/**
 * @brief 验证二维矩形数据的相等性
 */
bool VerifyRectData(const int* origin,
                    const int* result,
                    size_t     width,
                    size_t     height,
                    size_t     row_pitch_elements = 0)
{
    if (row_pitch_elements == 0)
    {
        row_pitch_elements = width;  // 默认情况下，行间距等于宽度
    }

    for (size_t y = 0; y < height; y++)
    {
        for (size_t x = 0; x < width; x++)
        {
            size_t origin_idx = y * row_pitch_elements + x;
            size_t result_idx = y * width + x;  // 结果总是紧密排列的

            if (origin[origin_idx] != result[result_idx])
            {
                std::cerr << format(
                                 "Error at position (%d, %d): expected %d, got "
                                 "%d\n") %
                                 x % y % origin[origin_idx] %
                                 result[result_idx];
                return false;
            }
        }
    }
    return true;
}

/**
 * @brief 打印矩形数据用于调试
 */
void PrintRectData(const int*         data,
                   size_t             width,
                   size_t             height,
                   size_t             row_pitch_elements = 0,
                   const std::string& label              = "")
{
    if (!label.empty())
    {
        std::cout << label << ":\n";
    }

    if (row_pitch_elements == 0)
    {
        row_pitch_elements = width;  // 默认情况下，行间距等于宽度
    }

    for (size_t y = 0; y < height; y++)
    {
        for (size_t x = 0; x < width; x++)
        {
            size_t idx = y * row_pitch_elements + x;
            std::cout << data[idx] << " ";
        }
        std::cout << "\n";
    }
    std::cout << "\n";
}

/**
 * @brief 基础的WriteBufferRect和ReadBufferRect功能测试
 */
BOOST_FIXTURE_TEST_CASE(BasicWriteBufferRectReadBufferRect,
                        RectBufferTestFixture)
{
    const size_t width  = 64;
    const size_t height = 32;
    const size_t total_elements =
        width * height * 2;  // 使用更大的缓冲区以允许偏移

    cl_mem buffer = clCreateBuffer(
        context_, CL_MEM_READ_WRITE, sizeof(int) * total_elements, NULL, NULL);
    BOOST_CHECK(buffer);
    BOOST_TEST_REQUIRE(buffer);

    // 创建一个二维数据源
    std::vector<int> source_data(total_elements, 0);
    for (size_t y = 0; y < height; y++)
    {
        for (size_t x = 0; x < width; x++)
        {
            source_data[y * width + x] = static_cast<int>(y * width + x);
        }
    }

    // 定义矩形区域参数
    size_t buffer_origin[3] = {0, 0, 0};  // 缓冲区偏移 (x, y, z) in bytes
    size_t host_origin[3]   = {0, 0, 0};  // 主机内存偏移 (x, y, z) in elements
    size_t region[3]        = {width * sizeof(int),
                               height,
                               1};  // 区域尺寸 (width in bytes, height, depth)

    // 写入矩形数据
    cl_int err =
        clEnqueueWriteBufferRect(queue_,
                                 buffer,
                                 CL_TRUE,  // 阻塞写入
                                 buffer_origin,
                                 host_origin,
                                 region,
                                 0,  // buffer_row_pitch (0 = use default)
                                 0,  // buffer_slice_pitch (0 = use default)
                                 width * sizeof(int),  // host_row_pitch
                                 0,  // host_slice_pitch (0 = use default)
                                 source_data.data(),
                                 0,      // 等待事件数量
                                 NULL,   // 等待事件列表
                                 NULL);  // 传出事件
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 读取矩形数据
    std::vector<int> result_data(width * height);
    err = clEnqueueReadBufferRect(queue_,
                                  buffer,
                                  CL_TRUE,  // 阻塞读取
                                  buffer_origin,
                                  host_origin,
                                  region,
                                  0,                    // buffer_row_pitch
                                  0,                    // buffer_slice_pitch
                                  width * sizeof(int),  // host_row_pitch
                                  0,                    // host_slice_pitch
                                  result_data.data(),
                                  0,      // 等待事件数量
                                  NULL,   // 等待事件列表
                                  NULL);  // 传出事件
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 验证数据是否正确
    bool is_correct = true;
    for (size_t i = 0; i < width * height; i++)
    {
        if (source_data[i] != result_data[i])
        {
            is_correct = false;
            break;
        }
    }
    BOOST_CHECK(is_correct);

    clReleaseMemObject(buffer);
}

/**
 * @brief 测试带偏移的WriteBufferRect和ReadBufferRect
 */
BOOST_FIXTURE_TEST_CASE(OffsetWriteBufferRectReadBufferRect,
                        RectBufferTestFixture)
{
    const size_t width           = 32;
    const size_t height          = 16;
    const size_t offset_elements = 100;  // 偏移100个整数的位置
    const size_t total_elements =
        offset_elements + (width * height * 2);  // 确保缓冲区足够大

    cl_mem buffer = clCreateBuffer(
        context_, CL_MEM_READ_WRITE, sizeof(int) * total_elements, NULL, NULL);
    BOOST_CHECK(buffer);
    BOOST_TEST_REQUIRE(buffer);

    // 创建一个二维数据源
    std::vector<int> source_data(width * height);
    for (size_t i = 0; i < width * height; i++)
    {
        source_data[i] = static_cast<int>(i + 1000);
    }

    // 定义矩形区域参数 - 从缓冲区中偏移位置开始
    size_t buffer_origin[3] = {
        offset_elements * sizeof(int), 0, 0};  // 偏移到缓冲区中的特定位置
    size_t host_origin[3] = {0, 0, 0};         // 主机内存从开头开始
    size_t region[3]      = {width * sizeof(int), height, 1};  // 区域尺寸

    // 写入矩形数据到偏移位置
    cl_int err =
        clEnqueueWriteBufferRect(queue_,
                                 buffer,
                                 CL_TRUE,
                                 buffer_origin,
                                 host_origin,
                                 region,
                                 0,                    // buffer_row_pitch
                                 0,                    // buffer_slice_pitch
                                 width * sizeof(int),  // host_row_pitch
                                 0,                    // host_slice_pitch
                                 source_data.data(),
                                 0,
                                 NULL,
                                 NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 从相同偏移位置读取矩形数据
    std::vector<int> result_data(width * height);
    err = clEnqueueReadBufferRect(queue_,
                                  buffer,
                                  CL_TRUE,
                                  buffer_origin,
                                  host_origin,
                                  region,
                                  0,                    // buffer_row_pitch
                                  0,                    // buffer_slice_pitch
                                  width * sizeof(int),  // host_row_pitch
                                  0,                    // host_slice_pitch
                                  result_data.data(),
                                  0,
                                  NULL,
                                  NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 验证数据是否正确
    bool is_correct = true;
    for (size_t i = 0; i < width * height; i++)
    {
        if (source_data[i] != result_data[i])
        {
            is_correct = false;
            break;
        }
    }
    BOOST_CHECK(is_correct);

    clReleaseMemObject(buffer);
}

/**
 * @brief 测试不同的行间距参数
 */
BOOST_FIXTURE_TEST_CASE(DifferentPitchWriteBufferRectReadBufferRect,
                        RectBufferTestFixture)
{
    const size_t width                   = 16;
    const size_t height                  = 8;
    const size_t host_row_pitch_elements = width + 4;  // 比宽度大，模拟填充
    const size_t total_elements =
        height * host_row_pitch_elements;                    // 主机内存大小
    const size_t buffer_size_elements = width * height * 2;  // 缓冲区大小

    cl_mem buffer = clCreateBuffer(context_,
                                   CL_MEM_READ_WRITE,
                                   sizeof(int) * buffer_size_elements,
                                   NULL,
                                   NULL);
    BOOST_CHECK(buffer);
    BOOST_TEST_REQUIRE(buffer);

    // 创建具有行间距的主机数据（每行后有额外元素）
    std::vector<int> host_data(total_elements);
    for (size_t y = 0; y < height; y++)
    {
        for (size_t x = 0; x < width; x++)
        {
            host_data[y * host_row_pitch_elements + x] =
                static_cast<int>(y * 100 + x);
        }
        // 在行的其余部分填充0（模拟填充）
        for (size_t x = width; x < host_row_pitch_elements; x++)
        {
            host_data[y * host_row_pitch_elements + x] = 0;
        }
    }

    // 定义矩形区域参数
    size_t buffer_origin[3] = {0, 0, 0};
    size_t host_origin[3]   = {0, 0, 0};
    size_t region[3]        = {width * sizeof(int), height, 1};

    // 写入矩形数据，使用特定的行间距
    cl_int err = clEnqueueWriteBufferRect(
        queue_,
        buffer,
        CL_TRUE,
        buffer_origin,
        host_origin,
        region,
        0,  // buffer_row_pitch (0 = use default)
        0,  // buffer_slice_pitch
        host_row_pitch_elements * sizeof(int),  // host_row_pitch (with padding)
        0,                                      // host_slice_pitch
        host_data.data(),
        0,
        NULL,
        NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 读取回紧密排列的数据
    std::vector<int> result_data(width * height);
    err = clEnqueueReadBufferRect(
        queue_,
        buffer,
        CL_TRUE,
        buffer_origin,
        host_origin,
        region,
        0,                    // buffer_row_pitch
        0,                    // buffer_slice_pitch
        width * sizeof(int),  // 紧密排列的host_row_pitch
        0,                    // host_slice_pitch
        result_data.data(),
        0,
        NULL,
        NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 验证数据是否正确（只检查有效数据部分）
    bool is_correct = true;
    for (size_t y = 0; y < height; y++)
    {
        for (size_t x = 0; x < width; x++)
        {
            int expected = y * 100 + x;
            int actual   = result_data[y * width + x];
            if (expected != actual)
            {
                std::cerr
                    << format("Mismatch at (%d, %d): expected %d, got %d\n") %
                           x % y % expected % actual;
                is_correct = false;
                break;
            }
        }
        if (!is_correct) break;
    }
    BOOST_CHECK(is_correct);

    clReleaseMemObject(buffer);
}

/**
 * @brief 测试非阻塞的WriteBufferRect和ReadBufferRect
 */
BOOST_FIXTURE_TEST_CASE(NonBlockingRectReadWrite, RectBufferTestFixture)
{
    const size_t width          = 32;
    const size_t height         = 16;
    const size_t total_elements = width * height;

    cl_mem buffer = clCreateBuffer(
        context_, CL_MEM_READ_WRITE, sizeof(int) * total_elements, NULL, NULL);
    BOOST_CHECK(buffer);
    BOOST_TEST_REQUIRE(buffer);

    // 创建数据源
    std::vector<int> source_data(total_elements);
    GeneratorRandom(source_data.data(), total_elements);

    // 非阻塞写入矩形数据
    size_t buffer_origin[3] = {0, 0, 0};
    size_t host_origin[3]   = {0, 0, 0};
    size_t region[3]        = {width * sizeof(int), height, 1};

    cl_event write_event = NULL;
    cl_int   err         = clEnqueueWriteBufferRect(queue_,
                                          buffer,
                                          CL_FALSE,  // 非阻塞写入
                                          buffer_origin,
                                          host_origin,
                                          region,
                                          0,
                                          0,
                                          width * sizeof(int),
                                          0,
                                          source_data.data(),
                                          0,
                                          NULL,
                                          &write_event);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 等待写入完成
    err = clWaitForEvents(1, &write_event);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 非阻塞读取矩形数据
    std::vector<int> result_data(total_elements);
    cl_event         read_event = NULL;
    err                         = clEnqueueReadBufferRect(queue_,
                                  buffer,
                                  CL_FALSE,  // 非阻塞读取
                                  buffer_origin,
                                  host_origin,
                                  region,
                                  0,
                                  0,
                                  width * sizeof(int),
                                  0,
                                  result_data.data(),
                                  0,
                                  NULL,
                                  &read_event);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 等待读取完成
    err = clWaitForEvents(1, &read_event);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 验证数据是否正确
    bool is_correct = true;
    for (size_t i = 0; i < total_elements; i++)
    {
        if (source_data[i] != result_data[i])
        {
            is_correct = false;
            break;
        }
    }
    BOOST_CHECK(is_correct);

    clReleaseEvent(write_event);
    clReleaseEvent(read_event);
    clReleaseMemObject(buffer);
}

/**
 * @brief 测试使用事件同步的矩形读写操作
 */
BOOST_FIXTURE_TEST_CASE(RectReadWriteWithEventSync, RectBufferTestFixture)
{
    const size_t width          = 64;
    const size_t height         = 32;
    const size_t total_elements = width * height;

    cl_mem buffer = clCreateBuffer(
        context_, CL_MEM_READ_WRITE, sizeof(int) * total_elements, NULL, NULL);
    BOOST_CHECK(buffer);
    BOOST_TEST_REQUIRE(buffer);

    // 创建数据源
    std::vector<int> source_data(total_elements);
    for (size_t i = 0; i < total_elements; i++)
    {
        source_data[i] = static_cast<int>(i % 10000);
    }

    // 定义矩形区域参数
    size_t buffer_origin[3] = {0, 0, 0};
    size_t host_origin[3]   = {0, 0, 0};
    size_t region[3]        = {width * sizeof(int), height, 1};

    // 写入矩形数据并获取事件
    cl_event write_event = NULL;
    cl_int   err         = clEnqueueWriteBufferRect(queue_,
                                          buffer,
                                          CL_FALSE,
                                          buffer_origin,
                                          host_origin,
                                          region,
                                          0,
                                          0,
                                          width * sizeof(int),
                                          0,
                                          source_data.data(),
                                          0,
                                          NULL,
                                          &write_event);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 读取矩形数据，等待写入事件完成
    std::vector<int> result_data(total_elements);
    cl_event         read_event = NULL;
    err                         = clEnqueueReadBufferRect(queue_,
                                  buffer,
                                  CL_FALSE,
                                  buffer_origin,
                                  host_origin,
                                  region,
                                  0,
                                  0,
                                  width * sizeof(int),
                                  0,
                                  result_data.data(),
                                  1,  // 等待1个事件
                                  &write_event,  // 等待写入事件
                                  &read_event);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 等待读取完成
    err = clWaitForEvents(1, &read_event);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    // 验证数据是否正确
    bool is_correct = true;
    for (size_t i = 0; i < total_elements; i++)
    {
        if (source_data[i] != result_data[i])
        {
            is_correct = false;
            break;
        }
    }
    BOOST_CHECK(is_correct);

    clReleaseEvent(write_event);
    clReleaseEvent(read_event);
    clReleaseMemObject(buffer);
}

/**
 * @brief 测试不同数据类型的矩形读写
 */
BOOST_FIXTURE_TEST_CASE(RectReadWriteDifferentTypes, RectBufferTestFixture)
{
    const size_t width          = 16;
    const size_t height         = 8;
    const size_t total_elements = width * height;

    // 测试float类型
    {
        cl_mem float_buffer = clCreateBuffer(context_,
                                             CL_MEM_READ_WRITE,
                                             sizeof(float) * total_elements * 2,
                                             NULL,
                                             NULL);
        BOOST_CHECK(float_buffer);

        std::vector<float> float_source_data(total_elements);
        for (size_t i = 0; i < total_elements; i++)
        {
            float_source_data[i] = static_cast<float>(i) * 0.5f;
        }

        size_t buffer_origin[3] = {0, 0, 0};
        size_t host_origin[3]   = {0, 0, 0};
        size_t region[3]        = {width * sizeof(float), height, 1};

        cl_int err = clEnqueueWriteBufferRect(queue_,
                                              float_buffer,
                                              CL_TRUE,
                                              buffer_origin,
                                              host_origin,
                                              region,
                                              0,
                                              0,
                                              width * sizeof(float),
                                              0,
                                              float_source_data.data(),
                                              0,
                                              NULL,
                                              NULL);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);

        std::vector<float> float_result_data(total_elements);
        err = clEnqueueReadBufferRect(queue_,
                                      float_buffer,
                                      CL_TRUE,
                                      buffer_origin,
                                      host_origin,
                                      region,
                                      0,
                                      0,
                                      width * sizeof(float),
                                      0,
                                      float_result_data.data(),
                                      0,
                                      NULL,
                                      NULL);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);

        // 验证浮点数据
        bool is_correct = true;
        for (size_t i = 0; i < total_elements; i++)
        {
            if (std::abs(float_source_data[i] - float_result_data[i]) > 1e-6f)
            {
                is_correct = false;
                break;
            }
        }
        BOOST_CHECK(is_correct);

        clReleaseMemObject(float_buffer);
    }

    // 测试char类型
    {
        cl_mem char_buffer = clCreateBuffer(context_,
                                            CL_MEM_READ_WRITE,
                                            sizeof(char) * total_elements * 2,
                                            NULL,
                                            NULL);
        BOOST_CHECK(char_buffer);

        std::vector<char> char_source_data(total_elements);
        for (size_t i = 0; i < total_elements; i++)
        {
            char_source_data[i] = static_cast<char>(i % 128);
        }

        size_t buffer_origin[3] = {0, 0, 0};
        size_t host_origin[3]   = {0, 0, 0};
        size_t region[3]        = {width * sizeof(char), height, 1};

        cl_int err = clEnqueueWriteBufferRect(queue_,
                                              char_buffer,
                                              CL_TRUE,
                                              buffer_origin,
                                              host_origin,
                                              region,
                                              0,
                                              0,
                                              width * sizeof(char),
                                              0,
                                              char_source_data.data(),
                                              0,
                                              NULL,
                                              NULL);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);

        std::vector<char> char_result_data(total_elements);
        err = clEnqueueReadBufferRect(queue_,
                                      char_buffer,
                                      CL_TRUE,
                                      buffer_origin,
                                      host_origin,
                                      region,
                                      0,
                                      0,
                                      width * sizeof(char),
                                      0,
                                      char_result_data.data(),
                                      0,
                                      NULL,
                                      NULL);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);

        // 验证char数据
        bool is_correct = true;
        for (size_t i = 0; i < total_elements; i++)
        {
            if (char_source_data[i] != char_result_data[i])
            {
                is_correct = false;
                break;
            }
        }
        BOOST_CHECK(is_correct);

        clReleaseMemObject(char_buffer);
    }
}

/**
 * @brief 测试大矩形数据的读写
 */
BOOST_FIXTURE_TEST_CASE(LargeRectReadWrite, RectBufferTestFixture)
{
    const size_t width          = 256;
    const size_t height         = 128;
    const size_t total_elements = width * height;

    cl_mem buffer = clCreateBuffer(context_,
                                   CL_MEM_READ_WRITE,
                                   sizeof(int) * total_elements * 2,
                                   NULL,
                                   NULL);
    if (!buffer)
    {
        BOOST_TEST_MESSAGE(
            "Skipping large rect test - buffer allocation failed (likely due "
            "to memory constraints)");
        return;
    }

    // 创建大矩形数据源
    std::vector<int> source_data(total_elements);
    for (size_t y = 0; y < height; y++)
    {
        for (size_t x = 0; x < width; x++)
        {
            source_data[y * width + x] = static_cast<int>(y * width + x);
        }
    }

    boost::timer::cpu_timer timer;

    // 写入大矩形数据
    size_t buffer_origin[3] = {0, 0, 0};
    size_t host_origin[3]   = {0, 0, 0};
    size_t region[3]        = {width * sizeof(int), height, 1};

    cl_int err = clEnqueueWriteBufferRect(queue_,
                                          buffer,
                                          CL_TRUE,
                                          buffer_origin,
                                          host_origin,
                                          region,
                                          0,
                                          0,
                                          width * sizeof(int),
                                          0,
                                          source_data.data(),
                                          0,
                                          NULL,
                                          NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    BOOST_TEST_MESSAGE("Write large rect data time: " << timer.format());

    // 读取大矩形数据
    std::vector<int> result_data(total_elements);
    timer.start();
    err = clEnqueueReadBufferRect(queue_,
                                  buffer,
                                  CL_TRUE,
                                  buffer_origin,
                                  host_origin,
                                  region,
                                  0,
                                  0,
                                  width * sizeof(int),
                                  0,
                                  result_data.data(),
                                  0,
                                  NULL,
                                  NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    BOOST_TEST_MESSAGE("Read large rect data time: " << timer.format());

    // 验证数据（只验证部分数据以提高效率）
    bool is_correct = true;
    for (size_t i = 0; i < total_elements; i += 1000)
    {  // 每1000个元素验证一个
        if (source_data[i] != result_data[i])
        {
            is_correct = false;
            break;
        }
    }
    // 验证最后几个元素
    for (size_t i = total_elements - 10; i < total_elements; i++)
    {
        if (source_data[i] != result_data[i])
        {
            is_correct = false;
            break;
        }
    }

    BOOST_CHECK(is_correct);

    clReleaseMemObject(buffer);
}

/**
 * @brief 测试边界情况 - 单行矩形
 */
BOOST_FIXTURE_TEST_CASE(SingleRowRectReadWrite, RectBufferTestFixture)
{
    const size_t width          = 128;
    const size_t height         = 1;  // 单行
    const size_t total_elements = width * height;

    cl_mem buffer = clCreateBuffer(
        context_, CL_MEM_READ_WRITE, sizeof(int) * width * 2, NULL, NULL);
    BOOST_CHECK(buffer);
    BOOST_TEST_REQUIRE(buffer);

    std::vector<int> source_data(total_elements);
    for (size_t i = 0; i < total_elements; i++)
    {
        source_data[i] = static_cast<int>(i + 2000);
    }

    size_t buffer_origin[3] = {0, 0, 0};
    size_t host_origin[3]   = {0, 0, 0};
    size_t region[3]        = {width * sizeof(int), height, 1};

    cl_int err = clEnqueueWriteBufferRect(queue_,
                                          buffer,
                                          CL_TRUE,
                                          buffer_origin,
                                          host_origin,
                                          region,
                                          0,
                                          0,
                                          width * sizeof(int),
                                          0,
                                          source_data.data(),
                                          0,
                                          NULL,
                                          NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    std::vector<int> result_data(total_elements);
    err = clEnqueueReadBufferRect(queue_,
                                  buffer,
                                  CL_TRUE,
                                  buffer_origin,
                                  host_origin,
                                  region,
                                  0,
                                  0,
                                  width * sizeof(int),
                                  0,
                                  result_data.data(),
                                  0,
                                  NULL,
                                  NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    BOOST_CHECK(
        VerifyRectData(source_data.data(), result_data.data(), width, height));

    clReleaseMemObject(buffer);
}

/**
 * @brief 测试边界情况 - 单列矩形
 */
BOOST_FIXTURE_TEST_CASE(SingleColumnRectReadWrite, RectBufferTestFixture)
{
    const size_t width          = 1;  // 单列
    const size_t height         = 128;
    const size_t total_elements = width * height;

    cl_mem buffer = clCreateBuffer(
        context_, CL_MEM_READ_WRITE, sizeof(int) * height * 2, NULL, NULL);
    BOOST_CHECK(buffer);
    BOOST_TEST_REQUIRE(buffer);

    std::vector<int> source_data(total_elements);
    for (size_t i = 0; i < total_elements; i++)
    {
        source_data[i] = static_cast<int>(i + 3000);
    }

    size_t buffer_origin[3] = {0, 0, 0};
    size_t host_origin[3]   = {0, 0, 0};
    size_t region[3]        = {width * sizeof(int), height, 1};

    cl_int err = clEnqueueWriteBufferRect(queue_,
                                          buffer,
                                          CL_TRUE,
                                          buffer_origin,
                                          host_origin,
                                          region,
                                          0,
                                          0,
                                          width * sizeof(int),
                                          0,
                                          source_data.data(),
                                          0,
                                          NULL,
                                          NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    std::vector<int> result_data(total_elements);
    err = clEnqueueReadBufferRect(queue_,
                                  buffer,
                                  CL_TRUE,
                                  buffer_origin,
                                  host_origin,
                                  region,
                                  0,
                                  0,
                                  width * sizeof(int),
                                  0,
                                  result_data.data(),
                                  0,
                                  NULL,
                                  NULL);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);

    BOOST_CHECK(
        VerifyRectData(source_data.data(), result_data.data(), width, height));

    clReleaseMemObject(buffer);
}
